using SharpDX;
using SharpDX.Direct3D11;
using System.Runtime.InteropServices;

namespace Engine.Graphics.VertexStructures
{
    public class CustomVertex
    {
        #region Public Structs

        [StructLayout(LayoutKind.Explicit, Size = 32)]
        public struct PositionColored
        {
            [FieldOffset(0)]
            private Vector3 position;

            [FieldOffset(16)]
            private Color4 color;

            /// <summary>
            /// Create the Vertex Element Array
            /// </summary>
            public static InputElement[] elements = new InputElement[]{
                new InputElement("POSITION", 0, SharpDX.DXGI.Format.R32G32B32_Float,0,0, InputClassification.PerVertexData, 0),//Position
                new InputElement("COLOR", 0, SharpDX.DXGI.Format.R32G32B32A32_Float,16,0, InputClassification.PerVertexData, 0),// Diffuse Color
            };

            public Color4 Color
            {
                get { return color; }
                set { color = value; }
            }

            public Vector3 Position
            {
                get { return position; }
                set { position = value; }
            }

            public float X
            {
                get { return this.position.X; }
                set { this.position.X = value; }
            }

            public float Y
            {
                get { return this.position.Y; }
                set { this.position.Y = value; }
            }

            public float Z
            {
                get { return this.position.Z; }
                set { this.position.Z = value; }
            }

            public override string ToString()
            {
                return this.position.ToString();
            }

            public PositionColored(Vector3 position, Color4 Color)
            {
                this.position = position;
                this.color = Color;
            }

            public PositionColored(Vector3 position, int Color)
            {
                this.position = position;
                this.color = new Color4(Color);
            }

            public static int SizeInBytes()
            {
                return Marshal.SizeOf(typeof(PositionColored));
            }
        }

        [StructLayout(LayoutKind.Explicit, Size = 48)]
        public struct PositionColoredTextured
        {
            public static InputElement[] elements = new InputElement[]{
                new InputElement("POSITION", 0, SharpDX.DXGI.Format.R32G32B32_Float,0,0, InputClassification.PerVertexData, 0),//Position
                new InputElement("COLOR", 0, SharpDX.DXGI.Format.R32G32B32A32_Float,12,0, InputClassification.PerVertexData, 0),// Diffuse Color
                new InputElement("TEXCOORD", 0, SharpDX.DXGI.Format.R32G32_Float,28,0, InputClassification.PerVertexData, 0),// UV1
            };

            public int Color
            {
                get { return color; }
                set { color = value; }
            }

            public Vector3 Position
            {
                get { return position; }
                set { position = value; }
            }

            public float Tu
            {
                get { return tu; }
                set { tu = value; }
            }

            public float Tv
            {
                get { return tv; }
                set { tv = value; }
            }

            internal static int SizeInBytes()
            {
                return Marshal.SizeOf(typeof(PositionColoredTextured));
            }

            [FieldOffset(0)]
            private Vector3 position;

            [FieldOffset(16)]
            private int color;

            [FieldOffset(20)]
            private float tu;

            [FieldOffset(24)]
            private float tv;
        }

        [StructLayout(LayoutKind.Explicit, Size = 32)]
        public struct PositionNormalTextured
        {
            public static InputElement[] elements = new InputElement[]{
                new InputElement("POSITION", 0, SharpDX.DXGI.Format.R32G32B32_Float,0,0, InputClassification.PerVertexData, 0),//Position
                new InputElement("NORMAL", 0, SharpDX.DXGI.Format.R32G32B32_Float,12,0, InputClassification.PerVertexData, 0), // Normal
                new InputElement("TEXCOORD", 0, SharpDX.DXGI.Format.R32G32_Float,24,0, InputClassification.PerVertexData, 0),// UV1
            };

            public float Nx
            {
                get { return this.Normal.X; }
                set { this.Normal.X = value; }
            }

            public float Ny
            {
                get { return this.Normal.Y; }
                set { this.Normal.Y = value; }
            }

            public float Nz
            {
                get { return this.Normal.Z; }
                set { this.Normal.Z = value; }
            }

            public float Tu
            {
                get { return this.UV.X; }
                set { this.UV.X = value; }
            }

            public float Tv
            {
                get { return this.UV.Y; }
                set { this.UV.Y = value; }
            }

            public float X
            {
                get { return this.Position.X; }
                set { this.Position.X = value; }
            }

            public float Y
            {
                get { return this.Position.Y; }
                set { this.Position.Y = value; }
            }

            public float Z
            {
                get { return this.Position.Z; }
                set { this.Position.Z = value; }
            }

            public PositionNormalTextured(Vector3 position, Vector3 normal, float Tu, float Tv)
            {
                this.Position = position;
                this.Normal = normal;
                this.UV = new Vector2(Tu, Tv);
            }

            internal static int SizeInBytes()
            {
                return Marshal.SizeOf(typeof(PositionNormalTextured));
            }

            [FieldOffset(0)]
            public Vector3 Position;

            [FieldOffset(12)]
            public Vector3 Normal;

            [FieldOffset(24)]
            public Vector2 UV;
        }

        [StructLayout(LayoutKind.Explicit, Size = 32)]
        public struct PositionTextured
        {
            public static InputElement[] elements = new InputElement[]{
                new InputElement("POSITION", 0, SharpDX.DXGI.Format.R32G32B32_Float,0,0, InputClassification.PerVertexData, 0),//Position
                new InputElement("TEXCOORD", 0, SharpDX.DXGI.Format.R32G32_Float,16,0, InputClassification.PerVertexData, 0),// UV1
            };

            public Vector3 Position
            {
                get { return position; }
                set { position = value; }
            }

            public Vector2 UVtex
            {
                get { return textureCoordinates; }
                set { textureCoordinates = value; }
            }

            public PositionTextured(Vector3 position, Vector2 UVCoordinates)
            {
                this.position = position;
                this.textureCoordinates = UVCoordinates;
            }

            public static int SizeInBytes()
            {
                return Marshal.SizeOf(typeof(PositionTextured));
            }

            [FieldOffset(0)]
            private Vector3 position;

            [FieldOffset(16)]
            private Vector2 textureCoordinates;
        }

        #endregion Public Structs

        #region Private Structs

        [StructLayout(LayoutKind.Explicit, Size = 32)]
        private struct TransformedColored
        {
            public static InputElement[] elements = new InputElement[]{
                new InputElement("POSITION", 0, SharpDX.DXGI.Format.R32G32B32_Float,0,0, InputClassification.PerVertexData, 0),//Position
                new InputElement("COLOR", 0, SharpDX.DXGI.Format.R32G32B32A32_Float,12,0, InputClassification.PerVertexData, 0),// Diffuse Color
            };

            public int Color
            {
                get { return color; }
                set { color = value; }
            }

            public Vector4 Position
            {
                get { return position; }
                set { position = value; }
            }

            public int SizeInBytes()
            {
                return Marshal.SizeOf(typeof(TransformedColored));
            }

            [FieldOffset(0)]
            private Vector4 position;

            [FieldOffset(12)]
            private int color;
        }

        #endregion Private Structs
    }
}